<script setup>
import { ref } from 'vue'
import { storeToRefs } from 'pinia'
import { usePiniaCounterStore } from '../stores/piniaCounter.js'

const store = usePiniaCounterStore()
const { count, doubleCount, lastChange } = storeToRefs(store)
const inputValue = ref('')

const setFromInput = () => {
  store.setCount(inputValue.value)
  inputValue.value = ''
}
</script>

<template>
  <div class="pinia-page">
    <h2 class="title">Pinia 状态管理教程</h2>
    <p class="desc">本页示例通过一个计数器演示 Pinia 的核心能力（state / getters / actions）。</p>

    <div class="card">
      <div class="metrics">
        <div class="metric">
          <div class="label">当前计数</div>
          <div class="value">{{ count }}</div>
        </div>
        <div class="metric">
          <div class="label">双倍值（getter）</div>
          <div class="value">{{ doubleCount }}</div>
        </div>
      </div>

      <div class="controls">
        <button class="btn primary" @click="store.increment">+1</button>
        <button class="btn primary" @click="store.decrement">-1</button>
        <button class="btn warning" @click="store.reset">重置</button>
        <button class="btn info" @click="store.undo">撤销</button>
      </div>

      <div class="setter">
        <input class="input" v-model="inputValue" placeholder="输入一个数字" />
        <button class="btn success" @click="setFromInput">设置计数</button>
      </div>

      <div class="history">
        <div class="label">最近一次变更</div>
        <div class="last" v-if="lastChange">{{ lastChange.type }} → {{ lastChange.value }}</div>
        <div class="last" v-else>暂无记录</div>
      </div>
    </div>

    <div class="tips">
      <div class="tip">在 `stores` 目录中定义 store：`defineStore(id, { state, getters, actions })`。</div>
      <div class="tip">在组件中通过 `usePiniaCounterStore()` 获取 store 实例。</div>
      <div class="tip">使用 `storeToRefs()` 将 state/getters 转为响应式引用。</div>
      <div class="tip">通过 actions 对状态进行集中更新，便于维护与调试。</div>
    </div>
    <!-- 完整文字教程 -->
    <div class="tutorial">
      <h3>Pinia 完整文字教程</h3>
      <p>Pinia 是 Vue 官方推荐的轻量状态管理库，支持 Vue 3/2，API 简洁、类型友好、开发体验好。你可以把 Store 理解为可共享的响应式数据中心。</p>

      <h4>1）安装与注册</h4>
      <p>在项目中安装 Pinia，并在入口文件注册：</p>
      <pre v-pre><code>npm i pinia

// src/main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')</code></pre>

      <h4>2）定义一个 Store</h4>
      <p>在 <code>src/stores</code> 下创建文件并使用 <code>defineStore</code>：</p>
      <pre v-pre><code>// src/stores/piniaCounter.js
import { defineStore } from 'pinia'

export const usePiniaCounterStore = defineStore('piniaCounter', {
  state: () => ({
    count: 0,
    history: []
  }),
  getters: {
    doubleCount: (state) => state.count * 2,
    lastChange: (state) => state.history[state.history.length - 1] ?? null
  },
  actions: {
    increment() { this.count++; this.history.push({ type: 'inc', value: this.count, at: Date.now() }) },
    decrement() { this.count--; this.history.push({ type: 'dec', value: this.count, at: Date.now() }) },
    setCount(val) {
      const n = Number(val) || 0
      this.count = n
      this.history.push({ type: 'set', value: n, at: Date.now() })
    },
    reset() { this.count = 0; this.history.push({ type: 'reset', value: this.count, at: Date.now() }) },
    undo() {
      if (this.history.length > 1) {
        this.history.pop()
        const last = this.history[this.history.length - 1]
        this.count = last.value
      }
    }
  }
})</code></pre>

      <h4>3）在组件中使用（组合式 API）</h4>
      <p>在你的组件中获取 Store 并绑定到 UI：</p>
      <pre v-pre><code>&lt;script setup&gt;
import { storeToRefs } from 'pinia'
import { usePiniaCounterStore } from '../stores/piniaCounter.js'

const store = usePiniaCounterStore()
const { count, doubleCount } = storeToRefs(store)

const inc = () => store.increment()
&lt;/script&gt;

&lt;template&gt;
  &lt;div&gt;{{ count }} / {{ doubleCount }}&lt;/div&gt;
  &lt;button @click="inc"&gt;+1&lt;/button&gt;
&lt;/template&gt;</code></pre>

      <h4>4）Getters 与计算属性</h4>
      <p>Getters 相当于 Store 的计算属性，可基于 state 派生数据，且具备缓存。推荐将通用派生逻辑收敛到 getters 中。</p>

      <h4>5）Actions：同步与异步</h4>
      <p>Actions 是修改状态的推荐入口，既可同步也可异步：</p>
      <pre v-pre><code>actions: {
  async fetchInitialCount() {
    // 示例：异步获取初始计数
    await new Promise(r => setTimeout(r, 300))
    this.count = 42
  }
}</code></pre>
      <p>在组件中调用：<code>await store.fetchInitialCount()</code>。</p>

      <h4>6）状态持久化（基础示例）</h4>
      <p>Pinia 原生不强制持久化，你可以使用订阅或插件实现：</p>
      <pre v-pre><code>// 订阅 store 变化并写入 localStorage
const store = usePiniaCounterStore()
store.$subscribe((mutation, state) => {
  localStorage.setItem('piniaCounter', JSON.stringify(state))
})

// 恢复：在 app 初始化或路由进入时
const saved = localStorage.getItem('piniaCounter')
if (saved) {
  const obj = JSON.parse(saved)
  store.count = obj.count
  store.history = obj.history
}</code></pre>

      <h4>7）组合式 vs 选项式</h4>
      <p>组合式 API 更符合现代 Vue 写法。若使用选项式，可用辅助映射：</p>
      <pre v-pre><code>import { mapStores, mapState, mapActions } from 'pinia'

computed: {
  ...mapStores(usePiniaCounterStore),
  ...mapState(usePiniaCounterStore, ['count', 'doubleCount'])
},
methods: {
  ...mapActions(usePiniaCounterStore, ['increment', 'reset'])
}</code></pre>

      <h4>8）调试与最佳实践</h4>
      <ul>
        <li>对复杂业务，统一通过 actions 更新状态，便于跟踪与测试。</li>
        <li>getter 尽量保持纯函数，不要在其中修改状态。</li>
        <li>避免在多处地方散落直接修改 state（简单场景可直接改），保持修改路径可控。</li>
        <li>将 Store 按领域拆分，如用户、文章、购物车等，提升可维护性。</li>
      </ul>

      <h4>9）本页示例如何运行</h4>
      <ul>
        <li>点击 +1、-1、重置、撤销：触发 actions 更新状态。</li>
        <li>在输入框内输入数字并点击设置计数：通过 <code>setCount</code> action 设置并记录历史。</li>
        <li>页面展示当前计数、双倍值，以及最近一次变更记录。</li>
      </ul>
    </div>
  </div>
  
</template>

<style scoped>
.pinia-page {
  padding: 20px;
}
.title {
  font-size: 24px;
  font-weight: 700;
  margin-bottom: 8px;
}
.desc {
  color: #666;
  margin-bottom: 16px;
}
.card {
  background: #fff;
  border: 1px solid #eee;
  border-radius: 12px;
  padding: 16px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.06);
}
.metrics {
  display: flex;
  gap: 16px;
}
.metric {
  flex: 1;
  background: #f7f9fc;
  border-radius: 10px;
  padding: 12px;
}
.label {
  font-size: 12px;
  color: #888;
}
.value {
  font-size: 28px;
  font-weight: 700;
}
.controls {
  display: flex;
  gap: 10px;
  margin-top: 16px;
}
.setter {
  display: flex;
  gap: 10px;
  margin-top: 12px;
}
.input {
  flex: 1;
  padding: 8px 10px;
  border: 1px solid #ddd;
  border-radius: 8px;
}
.btn {
  padding: 8px 14px;
  border: none;
  border-radius: 8px;
  cursor: pointer;
}
.btn.primary { background: #4e79ff; color: #fff; }
.btn.warning { background: #ff9f43; color: #fff; }
.btn.info { background: #00b8d9; color: #fff; }
.btn.success { background: #2ecc71; color: #fff; }
.history { margin-top: 12px; }
.last { margin-top: 6px; color: #333; }
.tips { margin-top: 20px; }
.tip { font-size: 13px; color: #555; margin-bottom: 4px; }
 .tutorial { margin-top: 24px; background: #fafafa; border: 1px solid #eee; border-radius: 10px; padding: 16px; }
 .tutorial h3 { font-size: 18px; font-weight: 700; margin-bottom: 10px; }
 .tutorial h4 { font-size: 15px; font-weight: 600; margin: 16px 0 8px; }
 .tutorial pre { background: #272822; color: #f8f8f2; padding: 12px; border-radius: 8px; overflow: auto; }
 .tutorial code { font-family: Consolas, Monaco, 'Courier New', monospace; }
 .tutorial ul { padding-left: 18px; }
</style>